package com.sharer.last.base.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.sharer.last.base.enums.ExceptionCode;
import com.sharer.last.base.interfaces.BaseExceptionCode;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * 统一返回类
 *
 * @ClassName R
 * @Author WangJin
 * @Date 2023/04/27/17:44
 * @Description
 * @Version 1.0
 */
@Builder
@Accessors(chain = true)
@Data
@AllArgsConstructor
public class R<T> implements Serializable {

    private static final int SUCCESS = 0;
    private static final int FAIL    = -1;

    /**
     * 调用是否成功标识，0：成功，其他异常
     */
    private int code;

    /**
     * 调用结果
     */
    private T data;

    /**
     * 附加数据
     */
    private Map<String, Object> extra;

    /***
     * 状态码
     */
    @JsonIgnore
    private int httpStatus;

    /**
     * 结果消息，如果调用成功，消息通常为空T
     */
    private String msg = "ok";

    public R() {
        super();
    }

    public R(int errCode, String errMsg) {
        this.code = errCode;
        this.msg = errMsg;
    }

    public R(BaseExceptionCode baseExceptionCode) {
        this.code = baseExceptionCode.getCode();
        this.msg = baseExceptionCode.getMsg();
    }

    public R(int errCode, T data, String errMsg) {
        this.code = errCode;
        this.data = data;
        this.msg = errMsg;
    }

    /**
     * 请求成功消息
     *
     * @return RPC调用结果
     */
    public static <T> R<T> ok() {
        return new R<>(SUCCESS, "ok");
    }

    /**
     * 请求成功消息
     *
     * @return RPC调用结果
     */
    public static <T> R<T> ok(String msg) {
        return new R<>(SUCCESS, msg);
    }

    /**
     * 请求成功消息
     *
     * @param data 结果
     * @return RPC调用结果
     */
    public static <T> R<T> ok(T data) {
        return new R<>(SUCCESS, data, "ok");
    }

    /**
     * 请求成功方法 ，data返回值，msg提示信息
     *
     * @param data 结果
     * @param msg  消息
     * @return RPC调用结果
     */
    public static <T> R<T> ok(T data, String msg) {
        return new R<>(SUCCESS, data, msg);
    }

    /**
     * 请求成功消息
     *
     * @return RPC调用结果
     */
    public static <T> R<T> ok(BaseExceptionCode apiErrorEnum) {
        return new R<>(SUCCESS, apiErrorEnum.getMsg());
    }

    public static <T> R<T> ok(T data, BaseExceptionCode apiErrorEnum) {
        return new R<>(SUCCESS, data, apiErrorEnum.getMsg());
    }

    /**
     * 请求成功别名
     *
     * @return RPC调用结果
     */
    public static <T> R<T> success(T data) {
        return new R<>(SUCCESS, data, "success");
    }

    public static <T> R<T> success(BaseExceptionCode apiErrorEnum) {
        return new R<>(SUCCESS, apiErrorEnum.getMsg());
    }

    public static <T> R<T> success(T data, BaseExceptionCode apiErrorEnum) {
        return new R<>(SUCCESS, data, apiErrorEnum.getMsg());
    }

    /*** 附加内容
     *
     * @param key
     * @param value
     * @return
     */
    public R putExtra(String key, Object value) {
        if (this.extra == null) {
            this.extra = new HashMap<String, Object>();
        }
        this.extra.put(key, value);
        return this;
    }

    public static <T> R<T> error(BaseExceptionCode apiErrorEnum) {
        return fail(apiErrorEnum.getCode(), apiErrorEnum.getCode() + ":" + apiErrorEnum.getMsg());
    }

    public static <T> R<T> error(BaseExceptionCode apiErrorEnum, String msg) {
        return fail(apiErrorEnum.getCode(), apiErrorEnum.getCode() + ":" + msg);
    }

    public static <T> R<T> fail(int code, String msg) {
        return new R<>(code, null, (msg == null || msg.isEmpty()) ? ExceptionCode.FAIL.getMsg() : msg);
    }

    public static <T> R<T> fail(String msg) {
        return fail(FAIL, msg);
    }


    public static <T> R<T> fail(BaseExceptionCode exceptionCode) {
        return fail(exceptionCode.getCode(), exceptionCode.getMsg());
    }

    public static <T> R<T> fail(BaseExceptionCode exceptionCode, String msg) {
        return fail(exceptionCode.getCode(), msg);
    }

    public static <T> R<T> fail(Throwable throwable) {
        return fail(throwable != null ? throwable.getMessage() : ExceptionCode.FAIL.getMsg());
    }

    /**
     * 操作
     *
     * @param isSave 保存状态
     * @return R
     */
    public static <T> R<T> handle(boolean isSave) {
        return isSave ? success(ExceptionCode.OK) : fail(ExceptionCode.ERROR);
    }
    public static <T> R<T> handle() {
        return  success(ExceptionCode.SUCCESS);
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

}
